"""
图形用户界面模块
提供基于 pygame 的现代化任务管理界面
"""

import pygame
import sys
from datetime import datetime, date
from typing import List, Optional, Dict, Any
from services.task_service import TaskService
from models.task import Task

# 初始化 pygame
pygame.init()

class Colors:
    """颜色常量 - 苹果风格配色"""
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    PRIMARY = (0, 122, 255)  # 苹果蓝
    SECONDARY = (142, 142, 147)  # 苹果灰
    SUCCESS = (52, 199, 89)  # 苹果绿
    WARNING = (255, 149, 0)  # 苹果橙
    DANGER = (255, 59, 48)  # 苹果红
    BACKGROUND = (248, 248, 248)  # 浅灰背景
    CARD_BG = (255, 255, 255)  # 卡片背景
    BORDER = (229, 229, 234)  # 边框颜色
    TEXT = (28, 28, 30)  # 主文本
    TEXT_SECONDARY = (99, 99, 102)  # 次要文本
    LIGHT_GRAY = (242, 242, 247)  # 浅灰
    HOVER = (0, 122, 255, 30)  # 悬停效果

class Fonts:
    """字体常量 - 优化中文显示"""
    try:
        # Windows 中文字体优先级
        TITLE = pygame.font.SysFont('microsoftyaheimicrosoftyaheiui,microsoftyahei,simhei,simsun,kaiti', 32, bold=True)
        LARGE = pygame.font.SysFont('microsoftyaheimicrosoftyaheiui,microsoftyahei,simhei,simsun,kaiti', 20, bold=True)
        NORMAL = pygame.font.SysFont('microsoftyaheimicrosoftyaheiui,microsoftyahei,simhei,simsun,kaiti', 16)
        SMALL = pygame.font.SysFont('microsoftyaheimicrosoftyaheiui,microsoftyahei,simhei,simsun,kaiti', 14)
        TINY = pygame.font.SysFont('microsoftyaheimicrosoftyaheiui,microsoftyahei,simhei,simsun,kaiti', 12)
    except:
        # 备用字体
        TITLE = pygame.font.Font(None, 32)
        LARGE = pygame.font.Font(None, 20)
        NORMAL = pygame.font.Font(None, 16)
        SMALL = pygame.font.Font(None, 14)
        TINY = pygame.font.Font(None, 12)

class Button:
    """按钮组件"""
    def __init__(self, x: int, y: int, width: int, height: int, text: str, color: tuple = Colors.PRIMARY):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.hover = False
        self.clicked = False
    
    def handle_event(self, event):
        """处理事件"""
        if event.type == pygame.MOUSEMOTION:
            self.hover = self.rect.collidepoint(event.pos)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if self.rect.collidepoint(event.pos):
                self.clicked = True
                return True
        return False
    
    def draw(self, screen):
        """绘制按钮"""
        color = tuple(min(255, c + 20) for c in self.color) if self.hover else self.color
        pygame.draw.rect(screen, color, self.rect, border_radius=8)
        
        text_surface = Fonts.NORMAL.render(self.text, True, Colors.WHITE)
        text_rect = text_surface.get_rect(center=self.rect.center)
        screen.blit(text_surface, text_rect)

class TaskCard:
    """任务卡片组件"""
    def __init__(self, task: Task, x: int, y: int, width: int, height: int):
        self.task = task
        self.rect = pygame.Rect(x, y, width, height)
        self.hover = False
        self.selected = False
    
    def handle_event(self, event):
        """处理事件"""
        if event.type == pygame.MOUSEMOTION:
            self.hover = self.rect.collidepoint(event.pos)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if self.rect.collidepoint(event.pos):
                self.selected = not self.selected
                return True
        return False
    
    def draw(self, screen):
        """绘制任务卡片"""
        # 背景色
        bg_color = Colors.PRIMARY if self.selected else Colors.CARD_BG
        if self.selected:
            bg_color = tuple(c if i < 3 else 50 for i, c in enumerate((*Colors.PRIMARY, 50)))
        
        # 绘制卡片背景
        pygame.draw.rect(screen, bg_color, self.rect, border_radius=12)
        
        # 绘制边框
        border_color = Colors.PRIMARY if self.selected else Colors.BORDER
        pygame.draw.rect(screen, border_color, self.rect, 2, border_radius=12)
        
        # 状态指示器
        status_colors = {
            'todo': Colors.SECONDARY,
            'in_progress': Colors.WARNING,
            'completed': Colors.SUCCESS
        }
        status_color = status_colors.get(self.task.status, Colors.SECONDARY)
        pygame.draw.circle(screen, status_color, (self.rect.x + 20, self.rect.y + 25), 6)
        
        # 优先级条
        priority_colors = {
            'high': Colors.DANGER,
            'medium': Colors.WARNING,
            'low': Colors.SUCCESS
        }
        priority_color = priority_colors.get(self.task.priority, Colors.SECONDARY)
        priority_rect = pygame.Rect(self.rect.x + 5, self.rect.y + 10, 3, self.rect.height - 20)
        pygame.draw.rect(screen, priority_color, priority_rect, border_radius=2)
        
        # 任务标题
        title_color = Colors.WHITE if self.selected else Colors.TEXT
        title_surface = Fonts.NORMAL.render(self.task.title[:30] + "..." if len(self.task.title) > 30 else self.task.title, True, title_color)
        screen.blit(title_surface, (self.rect.x + 40, self.rect.y + 15))
        
        # 任务描述
        if self.task.description:
            desc_color = Colors.WHITE if self.selected else Colors.TEXT_SECONDARY
            desc_text = self.task.description[:40] + "..." if len(self.task.description) > 40 else self.task.description
            desc_surface = Fonts.SMALL.render(desc_text, True, desc_color)
            screen.blit(desc_surface, (self.rect.x + 40, self.rect.y + 40))
        
        # 分类和截止日期
        info_y = self.rect.y + self.rect.height - 25
        info_color = Colors.WHITE if self.selected else Colors.TEXT_SECONDARY
        
        # 分类
        if self.task.category:
            category_surface = Fonts.TINY.render(f"[{self.task.category}]", True, info_color)
            screen.blit(category_surface, (self.rect.x + 40, info_y))
        
        # 截止日期
        if self.task.due_date:
            # 使用中文日期格式
            try:
                due_date = datetime.strptime(str(self.task.due_date), '%Y-%m-%d').date()
                due_text = f"截止: {due_date.strftime('%Y-%m-%d')}"
                if due_date < date.today():
                    due_text += " (已过期)"
                elif due_date == date.today():
                    due_text += " (今天)"
            except:
                due_text = f"截止: {self.task.due_date}"
            
            due_surface = Fonts.TINY.render(due_text, True, info_color)
            due_rect = due_surface.get_rect()
            screen.blit(due_surface, (self.rect.x + self.rect.width - due_rect.width - 15, info_y))

class TaskManagerGUI:
    """任务管理器图形界面"""
    
    def __init__(self, task_service: TaskService):
        self.task_service = task_service
        self.width = 1200
        self.height = 800
        self.screen = pygame.display.set_mode((self.width, self.height))
        pygame.display.set_caption("个人任务管理器")
        self.clock = pygame.time.Clock()
        self.running = True
        
        # 界面状态
        self.tasks = []
        self.task_cards = []
        self.selected_task = None
        self.scroll_offset = 0
        self.stats = {}
        
        # 对话框状态
        self.show_dialog = False
        self.editing_task = None
        self.dialog_title = ""
        self.dialog_description = ""
        self.dialog_category = ""
        self.dialog_due_date = ""
        self.dialog_priority = "medium"
        self.active_input = None
        
        # 按钮
        self.buttons = {
            'add': Button(20, 70, 80, 35, "添加任务", Colors.SUCCESS),
            'refresh': Button(110, 70, 60, 35, "刷新", Colors.PRIMARY),
            'complete': Button(180, 70, 80, 35, "完成任务", Colors.SUCCESS),
            'delete': Button(270, 70, 80, 35, "删除任务", Colors.DANGER),
        }
        
        # 加载数据
        self.load_data()
    
    def load_data(self):
        """加载任务数据"""
        try:
            self.tasks = self.task_service.list_tasks()
            self.stats = self.task_service.get_task_statistics()
            self.create_task_cards()
        except Exception as e:
            print(f"加载数据失败: {e}")
            self.tasks = []
            self.stats = {}
    
    def create_task_cards(self):
        """创建任务卡片"""
        self.task_cards = []
        card_width = 750
        card_height = 80
        start_y = 120
        
        for i, task in enumerate(self.tasks):
            y = start_y + i * (card_height + 10) - self.scroll_offset
            if y > -card_height and y < self.height:  # 只创建可见的卡片
                card = TaskCard(task, 20, y, card_width, card_height)
                self.task_cards.append(card)
    
    def handle_events(self):
        """处理事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            
            elif event.type == pygame.KEYDOWN:
                if self.show_dialog and self.active_input:
                    self.handle_text_input(event)
                elif event.key == pygame.K_ESCAPE:
                    if self.show_dialog:
                        self.close_dialog()
            
            elif event.type == pygame.TEXTINPUT:
                # 处理文本输入事件，支持中文输入
                if self.show_dialog and self.active_input:
                    self.handle_text_input_unicode(event)
            
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if self.show_dialog:
                    self.handle_dialog_click(event)
                else:
                    self.handle_main_click(event)
            
            elif event.type == pygame.MOUSEWHEEL:
                if not self.show_dialog:
                    self.scroll_offset -= event.y * 30
                    self.scroll_offset = max(0, min(self.scroll_offset, max(0, len(self.tasks) * 90 - 600)))
                    self.create_task_cards()
            
            # 处理按钮事件
            if not self.show_dialog:
                for name, button in self.buttons.items():
                    if button.handle_event(event):
                        self.handle_button_click(name)
            
            # 处理任务卡片事件
            for card in self.task_cards:
                if card.handle_event(event):
                    self.selected_task = card.task if card.selected else None
                    # 取消其他卡片的选中状态
                    for other_card in self.task_cards:
                        if other_card != card:
                            other_card.selected = False
    
    def handle_text_input(self, event):
        """处理键盘输入"""
        if event.key == pygame.K_BACKSPACE:
            if self.active_input == 'title':
                self.dialog_title = self.dialog_title[:-1]
            elif self.active_input == 'description':
                self.dialog_description = self.dialog_description[:-1]
            elif self.active_input == 'category':
                self.dialog_category = self.dialog_category[:-1]
            elif self.active_input == 'due_date':
                self.dialog_due_date = self.dialog_due_date[:-1]
        elif event.key == pygame.K_TAB:
            # 切换输入框
            inputs = ['title', 'description', 'category', 'due_date']
            current_index = inputs.index(self.active_input) if self.active_input in inputs else -1
            self.active_input = inputs[(current_index + 1) % len(inputs)]
    
    def handle_text_input_unicode(self, event):
        """处理Unicode文本输入，支持中文"""
        char = event.text
        if char and len(char.strip()) > 0:
            if self.active_input == 'title' and len(self.dialog_title) < 50:
                self.dialog_title += char
            elif self.active_input == 'description' and len(self.dialog_description) < 200:
                self.dialog_description += char
            elif self.active_input == 'category' and len(self.dialog_category) < 20:
                self.dialog_category += char
            elif self.active_input == 'due_date' and len(self.dialog_due_date) < 10:
                # 日期输入只允许数字和横线
                if char.isdigit() or char == '-':
                    self.dialog_due_date += char
    
    def handle_dialog_click(self, event):
        """处理对话框点击事件"""
        # 检查输入框点击
        dialog_x = (self.width - 500) // 2
        dialog_y = (self.height - 450) // 2
        
        input_fields = [
            ('title', dialog_y + 100),
            ('description', dialog_y + 160),
            ('category', dialog_y + 220),
            ('due_date', dialog_y + 280)
        ]
        
        for field_name, field_y in input_fields:
            field_rect = pygame.Rect(dialog_x + 20, field_y + 20, 460, 30)
            if field_rect.collidepoint(event.pos):
                self.active_input = field_name
                return
        
        # 检查优先级选择
        priority_y = dialog_y + 340
        priorities = [("低", "low"), ("中", "medium"), ("高", "high")]
        for i, (label, value) in enumerate(priorities):
            x = dialog_x + 100 + i * 80
            if pygame.Rect(x - 10, priority_y, 60, 20).collidepoint(event.pos):
                self.dialog_priority = value
                return
        
        # 检查按钮点击
        if hasattr(self, 'save_button_rect') and self.save_button_rect.collidepoint(event.pos):
            self.save_task()
        elif hasattr(self, 'cancel_button_rect') and self.cancel_button_rect.collidepoint(event.pos):
            self.close_dialog()
    
    def handle_main_click(self, event):
        """处理主界面点击事件"""
        pass
    
    def handle_button_click(self, button_name):
        """处理按钮点击"""
        if button_name == 'add':
            self.show_add_dialog()
        elif button_name == 'refresh':
            self.load_data()
        elif button_name == 'complete':
            if self.selected_task:
                try:
                    self.task_service.complete_task(self.selected_task.id)
                    self.load_data()
                    self.selected_task = None
                except Exception as e:
                    print(f"完成任务失败: {e}")
        elif button_name == 'delete':
            if self.selected_task:
                try:
                    self.task_service.delete_task(self.selected_task.id)
                    self.load_data()
                    self.selected_task = None
                except Exception as e:
                    print(f"删除任务失败: {e}")
    
    def show_add_dialog(self):
        """显示添加任务对话框"""
        self.show_dialog = True
        self.editing_task = None
        self.dialog_title = ""
        self.dialog_description = ""
        self.dialog_category = ""
        self.dialog_due_date = ""
        self.dialog_priority = "medium"
        self.active_input = "title"
    
    def close_dialog(self):
        """关闭对话框"""
        self.show_dialog = False
        self.editing_task = None
        self.active_input = None
    
    def save_task(self):
        """保存任务"""
        if not self.dialog_title.strip():
            return
        
        try:
            # 验证日期格式
            due_date = None
            if self.dialog_due_date.strip():
                try:
                    datetime.strptime(self.dialog_due_date.strip(), '%Y-%m-%d')
                    due_date = self.dialog_due_date.strip()
                except ValueError:
                    print("日期格式错误，请使用 YYYY-MM-DD 格式")
                    return
            
            # 创建任务
            task_data = {
                'title': self.dialog_title.strip(),
                'description': self.dialog_description.strip() if self.dialog_description.strip() else None,
                'category': self.dialog_category.strip() if self.dialog_category.strip() else None,
                'priority': self.dialog_priority,
                'due_date': due_date
            }
            
            self.task_service.add_task(**task_data)
            self.load_data()
            self.close_dialog()
            
        except Exception as e:
            print(f"保存任务失败: {e}")
    
    def draw(self):
        """绘制界面"""
        # 清空屏幕
        self.screen.fill(Colors.BACKGROUND)
        
        # 绘制头部
        self.draw_header()
        
        # 绘制任务列表
        self.draw_task_list()
        
        # 绘制统计面板
        self.draw_stats_panel()
        
        # 绘制任务编辑对话框
        if self.show_dialog:
            self.draw_task_dialog()
        
        pygame.display.flip()
        self.clock.tick(60)
    
    def draw_header(self):
        """绘制头部"""
        # 背景
        header_rect = pygame.Rect(0, 0, self.width, 110)
        pygame.draw.rect(self.screen, Colors.WHITE, header_rect)
        pygame.draw.line(self.screen, Colors.BORDER, (0, 110), (self.width, 110), 1)
        
        # 标题
        title_surface = Fonts.TITLE.render("个人任务管理器", True, Colors.TEXT)
        self.screen.blit(title_surface, (20, 20))
        
        # 当前日期
        current_date = datetime.now().strftime("%Y年%m月%d日 %A")
        date_surface = Fonts.NORMAL.render(current_date, True, Colors.TEXT_SECONDARY)
        date_rect = date_surface.get_rect()
        self.screen.blit(date_surface, (self.width - date_rect.width - 20, 25))
        
        # 绘制按钮
        for button in self.buttons.values():
            button.draw(self.screen)
    
    def draw_task_list(self):
        """绘制任务列表"""
        # 列表区域背景
        list_rect = pygame.Rect(10, 120, 780, self.height - 130)
        pygame.draw.rect(self.screen, Colors.WHITE, list_rect, border_radius=12)
        pygame.draw.rect(self.screen, Colors.BORDER, list_rect, 1, border_radius=12)
        
        # 列表标题
        list_title = Fonts.LARGE.render("任务列表", True, Colors.TEXT)
        self.screen.blit(list_title, (30, 130))
        
        # 绘制任务卡片
        for card in self.task_cards:
            card.draw(self.screen)
        
        # 如果没有任务，显示提示
        if not self.tasks:
            no_task_text = Fonts.NORMAL.render("暂无任务，点击"添加任务"开始使用", True, Colors.TEXT_SECONDARY)
            text_rect = no_task_text.get_rect(center=(400, 400))
            self.screen.blit(no_task_text, text_rect)
    
    def draw_stats_panel(self):
        """绘制统计面板"""
        panel_x = 800
        panel_width = 380
        panel_rect = pygame.Rect(panel_x, 120, panel_width, self.height - 130)
        pygame.draw.rect(self.screen, Colors.WHITE, panel_rect, border_radius=12)
        pygame.draw.rect(self.screen, Colors.BORDER, panel_rect, 1, border_radius=12)
        
        # 面板标题
        panel_title = Fonts.LARGE.render("任务统计", True, Colors.TEXT)
        self.screen.blit(panel_title, (panel_x + 20, 130))
        
        # 统计信息
        y_offset = 170
        stats_items = [
            ("总任务数", self.stats.get('total', 0), Colors.TEXT),
            ("待办任务", self.stats.get('todo', 0), Colors.WARNING),
            ("进行中", self.stats.get('in_progress', 0), Colors.PRIMARY),
            ("已完成", self.stats.get('completed', 0), Colors.SUCCESS),
            ("完成率", f"{self.stats.get('completion_rate', 0):.1f}%", Colors.PRIMARY),
        ]
        
        for label, value, color in stats_items:
            label_surface = Fonts.NORMAL.render(f"{label}:", True, Colors.TEXT)
            value_surface = Fonts.NORMAL.render(str(value), True, color)
            
            self.screen.blit(label_surface, (panel_x + 20, y_offset))
            self.screen.blit(value_surface, (panel_x + 150, y_offset))
            y_offset += 30
        
        # 过期任务警告
        overdue_count = self.stats.get('overdue_count', 0)
        if overdue_count > 0:
            y_offset += 20
            warning_text = f"过期任务: {overdue_count} 个"
            warning_surface = Fonts.NORMAL.render(warning_text, True, Colors.DANGER)
            self.screen.blit(warning_surface, (panel_x + 20, y_offset))
        
        # 即将到期任务
        upcoming_count = self.stats.get('upcoming_count', 0)
        if upcoming_count > 0:
            y_offset += 30
            upcoming_text = f"即将到期: {upcoming_count} 个"
            upcoming_surface = Fonts.NORMAL.render(upcoming_text, True, Colors.WARNING)
            self.screen.blit(upcoming_surface, (panel_x + 20, y_offset))
    
    def draw_task_dialog(self):
        """绘制任务编辑对话框"""
        # 绘制半透明背景
        overlay = pygame.Surface((self.width, self.height))
        overlay.set_alpha(128)
        overlay.fill(Colors.BLACK)
        self.screen.blit(overlay, (0, 0))
        
        # 对话框尺寸和位置
        dialog_width = 500
        dialog_height = 450
        dialog_x = (self.width - dialog_width) // 2
        dialog_y = (self.height - dialog_height) // 2
        
        # 绘制对话框背景
        dialog_rect = pygame.Rect(dialog_x, dialog_y, dialog_width, dialog_height)
        pygame.draw.rect(self.screen, Colors.WHITE, dialog_rect, border_radius=12)
        pygame.draw.rect(self.screen, Colors.BORDER, dialog_rect, 2, border_radius=12)
        
        # 绘制标题
        title = "编辑任务" if self.editing_task else "添加任务"
        title_surface = Fonts.TITLE.render(title, True, Colors.TEXT)
        title_rect = title_surface.get_rect(centerx=dialog_x + dialog_width//2, y=dialog_y + 20)
        self.screen.blit(title_surface, title_rect)
        
        # 绘制输入框
        y_offset = dialog_y + 80
        
        # 标题输入框
        self.draw_input_field("任务标题:", self.dialog_title, dialog_x + 20, y_offset, dialog_width - 40, 'title')
        y_offset += 60
        
        # 描述输入框
        self.draw_input_field("任务描述:", self.dialog_description, dialog_x + 20, y_offset, dialog_width - 40, 'description')
        y_offset += 60
        
        # 分类输入框
        self.draw_input_field("任务分类:", self.dialog_category, dialog_x + 20, y_offset, dialog_width - 40, 'category')
        y_offset += 60
        
        # 截止日期输入框
        self.draw_input_field("截止日期 (YYYY-MM-DD):", self.dialog_due_date, dialog_x + 20, y_offset, dialog_width - 40, 'due_date')
        y_offset += 60
        
        # 优先级选择
        priority_label = Fonts.NORMAL.render("优先级:", True, Colors.TEXT)
        self.screen.blit(priority_label, (dialog_x + 20, y_offset))
        
        priorities = [("低", "low"), ("中", "medium"), ("高", "high")]
        for i, (label, value) in enumerate(priorities):
            x = dialog_x + 100 + i * 80
            color = Colors.PRIMARY if self.dialog_priority == value else Colors.LIGHT_GRAY
            pygame.draw.circle(self.screen, color, (x, y_offset + 10), 8)
            text = Fonts.SMALL.render(label, True, Colors.TEXT)
            self.screen.blit(text, (x + 15, y_offset + 5))
        
        y_offset += 40
        
        # 按钮
        button_width = 80
        button_height = 35
        
        # 保存按钮
        save_x = dialog_x + dialog_width - 200
        save_y = dialog_y + dialog_height - 60
        save_rect = pygame.Rect(save_x, save_y, button_width, button_height)
        pygame.draw.rect(self.screen, Colors.SUCCESS, save_rect, border_radius=5)
        save_text = Fonts.NORMAL.render("保存", True, Colors.WHITE)
        save_text_rect = save_text.get_rect(center=save_rect.center)
        self.screen.blit(save_text, save_text_rect)
        
        # 取消按钮
        cancel_x = dialog_x + dialog_width - 100
        cancel_y = dialog_y + dialog_height - 60
        cancel_rect = pygame.Rect(cancel_x, cancel_y, button_width, button_height)
        pygame.draw.rect(self.screen, Colors.LIGHT_GRAY, cancel_rect, border_radius=5)
        cancel_text = Fonts.NORMAL.render("取消", True, Colors.TEXT)
        cancel_text_rect = cancel_text.get_rect(center=cancel_rect.center)
        self.screen.blit(cancel_text, cancel_text_rect)
        
        # 存储按钮矩形用于点击检测
        self.save_button_rect = save_rect
        self.cancel_button_rect = cancel_rect
    
    def draw_input_field(self, label: str, value: str, x: int, y: int, width: int, field_name: str):
        """绘制输入框"""
        # 标签
        label_surface = Fonts.NORMAL.render(label, True, Colors.TEXT)
        self.screen.blit(label_surface, (x, y))
        
        # 输入框
        input_rect = pygame.Rect(x, y + 20, width, 30)
        border_color = Colors.PRIMARY if self.active_input == field_name else Colors.BORDER
        pygame.draw.rect(self.screen, Colors.WHITE, input_rect)
        pygame.draw.rect(self.screen, border_color, input_rect, 2, border_radius=4)
        
        # 输入文本
        # 输入文本
        if value:
            text_surface = Fonts.NORMAL.render(value, True, Colors.TEXT)
            text_rect = text_surface.get_rect()
            if text_rect.width > width - 10:
                # 文本太长，显示末尾部分
                visible_text = value
                while Fonts.NORMAL.size(visible_text)[0] > width - 10 and visible_text:
                    visible_text = visible_text[1:]
                text_surface = Fonts.NORMAL.render(visible_text, True, Colors.TEXT)
            self.screen.blit(text_surface, (x + 5, y + 25))
        
        # 光标显示
        if self.active_input == field_name:
            cursor_x = x + 5 + Fonts.NORMAL.size(value)[0]
            if pygame.time.get_ticks() % 1000 < 500:  # 闪烁效果
                pygame.draw.line(self.screen, Colors.TEXT, 
                               (cursor_x, y + 25), (cursor_x, y + 45), 1)
    
    def run(self):
        """运行GUI主循环"""
        print("🎨 启动图形界面...")
        
        while self.running:
            self.handle_events()
            self.draw()
        
        pygame.quit()
        return 0
